Let us set some global options for all code chunks in this
document.
# Set seed for reproducibility
set.seed(1982)
# Set global options for all code chunks
knitr::opts_chunk$set(
# Disable messages printed by R code chunks
message = FALSE,
# Disable warnings printed by R code chunks
warning = FALSE,
# Show R code within code chunks in output
echo = TRUE,
# Include both R code and its results in output
include = TRUE,
# Evaluate R code chunks
eval = TRUE,
# Enable caching of R code chunks for faster rendering
cache = FALSE,
# Align figures in the center of the output
fig.align = "center",
# Enable retina display for high-resolution figures
retina = 2,
# Show errors in the output instead of stopping rendering
error = TRUE,
# Do not collapse code and output into a single block
collapse = FALSE
)
# inla.upgrade(testing = TRUE)
# remotes::install_github("inlabru-org/inlabru", ref = "devel")
# remotes::install_github("davidbolin/rspde", ref = "devel")
# remotes::install_github("davidbolin/metricgraph", ref = "devel")
library(INLA)
library(inlabru)
library(rSPDE)
library(MetricGraph)
library(grateful)
library(plotly)
We want to solve the fractional diffusion equation \[\begin{equation}
\label{eq:maineq}
\partial_t u+(\kappa^2-\Delta_\Gamma)^{\frac{\alpha}{2}} u=f \text {
on } \Gamma \times(0, T), \quad u(0)=u_0 \text { on } \Gamma,
\end{equation}\] where \(u\)
satisfies the Kirchhoff vertex conditions \[\begin{equation}
\label{eq:Kcond}
\left\{\phi\in C(\Gamma)\;\Big|\; \forall v\in V:
\sum_{e\in\mathcal{E}_v}\partial_e \phi(v)=0 \right\}
\end{equation}\]
Let us start by building a graph.
graph <- metric_graph$new(perform_merges = TRUE,
tolerance = list(edge_edge = 1e-3,
vertex_vertex = 1e-3,
edge_vertex = 1e-3))
graph$plot()

graph$build_mesh(h = 0.05)
Let \(\alpha\in(0,2]\) and \(U_h^\tau\) denote the sequence of
approximations of the solution to the weak form of problem \(\eqref{eq:maineq}\) at each time step on a
mesh indexed by \(h\). Let \(z=0\) and \(U^0_h
= P_hu_0\). For \(k=0,\dots,
N-1\), \(U_h^{k+1}\in V_h\)
solves the following scheme \[\begin{align}
\label{system:fully_discrete_scheme}
\langle\delta U_h^{k+1},\phi\rangle +
\mathfrak{a}(U_h^{k+1},\phi) = \langle f^{k+1},\phi\rangle
,\quad\forall\phi\in V_h,
\end{align}\] where \(f^{k+1} =
\displaystyle\dfrac{1}{\tau}\int_{t_k}^{t^{k+1}}f(t)dt\). The
solution can be represented as \[\begin{align*}
U_h^k(s) = \sum_{j=1}^{N_h}u_j^k\psi_j(s)
\end{align*}\] Replacing this into \(\eqref{system:fully_discrete_scheme}\)
yields the following linear system \[\begin{align*}
\sum_{j=1}^{N_h}u_j^{k+1}[(\psi_j,\psi_i)_{L_2(\Gamma)}+
\tau\mathfrak{a}(\psi_j,\psi_i)] =
\sum_{j=1}^{N_h}u_j^{k}(\psi_j,\psi_i)_{L_2(\Gamma)}+\tau(
f^{k+1},\psi_i)_{L_2(\Gamma)}
\end{align*}\] for \(i = 1,\dots,
N_h\). In matrix notation, \[\begin{align}
\label{diff_eq_discrete}
(C+\tau A)U^{k+1} = CU^k+\tau F^{k+1},
\end{align}\] where \(C\) has
entries \(C_{ij} =
(\psi_j,\psi_i)_{L_2(\Gamma)}\), \(A\) has entries \(A_{ij} = \mathfrak{a}(\psi_j,\psi_i)\),
\(U^k\) has entries \(u_j^k\), and \(F^k\) has entries \(( f^{k},\psi_i)_{L_2(\Gamma)}\). By
multiplying both sides by \(A^{-1}\)
and considering its operator-based rational approximation \(P_\ell^{-1}P_r\), we arrive at \((P_rC+\tau P_\ell)U^{k+1} = P_r(CU^k+\tau
F^{k+1})\).
# Compute the FEM matrices
graph$compute_fem()
G <- graph$mesh$G
C <- graph$mesh$C
x <- graph$mesh$V[, 1]
y <- graph$mesh$V[, 2]
# Initial condition
U_0 <- 10*exp(-((x-4)^2 + (y-4)^2))
# Define the time step
time_step <- 0.1
# Define the right-hand side function
fun <- function(t) {return(sin(t)*((x-4)^2 - (y-4)^2))}
# Define the time discretization
time_seq <- seq(0,pi, by = time_step)
# Compute the right-hand side function at each time step
fun_mat <- do.call(cbind, lapply(time_seq, fun))
# Define the parameters
kappa <- 1
L <- kappa^2*C + G
alpha <- 0.8
beta <- alpha/2
op <- fractional.operators(L, beta, C, scale.factor = kappa^2, m = 1)
Pl <- op$Pl
Pr <- op$Pr
funF <- C %*% fun_mat
# Precompute the LHS matrix
LHS <- Pr %*% C + time_step * Pl
# Initialize U matrix to store solution at each time step
U_mat <- matrix(NA, nrow = nrow(C), ncol = length(time_seq))
U_mat[, 1] <- U_0
# Time-stepping loop
for (k in 1:(length(time_seq) - 1)) {
RHS <- Pr %*% (C %*% U_mat[, k] + time_step * funF[, k + 1])
U_mat[, k + 1] <- as.matrix(solve(LHS, RHS))
}
# Plot the initial condition
p_ini <- graph$plot_function(X = U_0,
vertex_size = 1,
type = "plotly",
edge_color = "black",
edge_width = 3,
line_color = "blue",
line_width = 3)
p_ini
# Plot the movie of f
p_f <- graph$plot_movie(fun_mat)
p_f$x$layout$scene$xaxis$range <- range(x)
p_f$x$layout$scene$yaxis$range <- range(y)
p_f$x$layout$scene$zaxis$range <- range(fun_mat)
p_f
# Plot the movie of the solution
p_sol <- graph$plot_movie(U_mat)
p_sol$x$layout$scene$xaxis$range <- range(x)
p_sol$x$layout$scene$yaxis$range <- range(y)
p_sol$x$layout$scene$zaxis$range <- range(U_mat)
p_sol
References
cite_packages(output = "paragraph", out.dir = ".")
We used R version 4.4.3 (R Core Team
2025) and the following R packages: htmltools v. 0.5.8.1 (Cheng et al. 2024), INLA v. 25.4.16 (Rue, Martino, and Chopin 2009; Lindgren, Rue, and
Lindström 2011; Martins et al. 2013; Lindgren and Rue 2015; De Coninck
et al. 2016; Rue et al. 2017; Verbosio et al. 2017; Bakka et al. 2018;
Kourounis, Fuchs, and Schenk 2018), inlabru v. 2.12.0.9012 (Yuan et al. 2017; Bachl et al. 2019), knitr v.
1.48 (Xie 2014, 2015, 2024), MetricGraph
v. 1.4.1.9000 (Bolin, Simas, and Wallin 2023a,
2023b, 2024, 2025; Bolin et al. 2024), plotly v. 4.10.4 (Sievert 2020), rmarkdown v. 2.28 (Xie, Allaire, and Grolemund 2018; Xie, Dervieux, and
Riederer 2020; Allaire et al. 2024), rSPDE v. 2.5.1.9000 (Bolin and Kirchner 2020; Bolin and Simas 2023; Bolin,
Simas, and Xiong 2024), xaringanExtra v. 0.8.0 (Aden-Buie and Warkentin 2024).
Allaire, JJ, Yihui Xie, Christophe Dervieux, Jonathan McPherson, Javier
Luraschi, Kevin Ushey, Aron Atkins, et al. 2024.
rmarkdown: Dynamic Documents for r.
https://github.com/rstudio/rmarkdown.
Bachl, Fabian E., Finn Lindgren, David L. Borchers, and Janine B.
Illian. 2019.
“inlabru: An
R Package for Bayesian Spatial Modelling from
Ecological Survey Data.” Methods in Ecology and
Evolution 10: 760–66.
https://doi.org/10.1111/2041-210X.13168.
Bakka, Haakon, Håvard Rue, Geir-Arne Fuglstad, Andrea I. Riebler, David
Bolin, Janine Illian, Elias Krainski, Daniel P. Simpson, and Finn K.
Lindgren. 2018.
“Spatial Modelling with INLA:
A Review.” WIRES (Invited Extended Review)
xx (Feb): xx–.
http://arxiv.org/abs/1802.06350.
Bolin, David, and Kristin Kirchner. 2020.
“The Rational
SPDE Approach for Gaussian Random Fields with
General Smoothness.” Journal of Computational and Graphical
Statistics 29 (2): 274–85.
https://doi.org/10.1080/10618600.2019.1665537.
Bolin, David, Mihály Kovács, Vivek Kumar, and Alexandre B. Simas. 2024.
“Regularity and Numerical Approximation of Fractional Elliptic
Differential Equations on Compact Metric Graphs.” Mathematics
of Computation 93 (349): 2439–72.
https://doi.org/10.1090/mcom/3929.
Bolin, David, and Alexandre B. Simas. 2023.
rSPDE: Rational Approximations of Fractional
Stochastic Partial Differential Equations.
https://CRAN.R-project.org/package=rSPDE.
Bolin, David, Alexandre B. Simas, and Jonas Wallin. 2023a.
MetricGraph: Random Fields on Metric Graphs.
https://CRAN.R-project.org/package=MetricGraph.
———. 2023b.
“Statistical Inference for Gaussian Whittle-Matérn
Fields on Metric Graphs.” arXiv Preprint
arXiv:2304.10372.
https://doi.org/10.48550/arXiv.2304.10372.
———. 2024.
“Gaussian Whittle-Matérn Fields on Metric
Graphs.” Bernoulli 30 (2): 1611–39.
https://doi.org/10.3150/23-BEJ1647.
———. 2025.
“Markov Properties of Gaussian Random Fields on Compact
Metric Graphs.” Bernoulli.
https://doi.org/10.48550/arXiv.2304.03190.
Bolin, David, Alexandre B. Simas, and Zhen Xiong. 2024.
“Covariance-Based Rational Approximations of Fractional SPDEs for
Computationally Efficient Bayesian Inference.” Journal of
Computational and Graphical Statistics 33 (1): 64–74.
https://doi.org/10.1080/10618600.2023.2231051.
De Coninck, Arne, Bernard De Baets, Drosos Kourounis, Fabio Verbosio,
Olaf Schenk, Steven Maenhout, and Jan Fostier. 2016.
“Needles: Toward Large-Scale Genomic Prediction with
Marker-by-Environment Interaction.” Genetics 203 (1):
543–55.
https://doi.org/10.1534/genetics.115.179887.
Kourounis, D., A. Fuchs, and O. Schenk. 2018.
“Towards the Next
Generation of Multiperiod Optimal Power Flow Solvers.” IEEE
Transactions on Power Systems PP (99): 1–10.
https://doi.org/10.1109/TPWRS.2017.2789187.
Lindgren, Finn, and Håvard Rue. 2015.
“Bayesian Spatial Modelling
with R-INLA.” Journal of
Statistical Software 63 (19): 1–25.
http://www.jstatsoft.org/v63/i19/.
Lindgren, Finn, Håvard Rue, and Johan Lindström. 2011. “An
Explicit Link Between Gaussian Fields and
Gaussian Markov Random Fields: The Stochastic
Partial Differential Equation Approach (with Discussion).”
Journal of the Royal Statistical Society B 73 (4): 423–98.
Martins, Thiago G., Daniel Simpson, Finn Lindgren, and Håvard Rue. 2013.
“Bayesian Computing with INLA: New
Features.” Computational Statistics and Data Analysis
67: 68–83.
R Core Team. 2025.
R: A Language and Environment for
Statistical Computing. Vienna, Austria: R Foundation for
Statistical Computing.
https://www.R-project.org/.
Rue, Håvard, Sara Martino, and Nicholas Chopin. 2009. “Approximate
Bayesian Inference for Latent Gaussian Models
Using Integrated Nested Laplace Approximations (with
Discussion).” Journal of the Royal Statistical Society B
71: 319–92.
Rue, Håvard, Andrea I. Riebler, Sigrunn H. Sørbye, Janine B. Illian,
Daniel P. Simpson, and Finn K. Lindgren. 2017.
“Bayesian Computing
with INLA: A Review.” Annual
Reviews of Statistics and Its Applications 4 (March): 395–421.
http://arxiv.org/abs/1604.00860.
Sievert, Carson. 2020.
Interactive Web-Based Data Visualization with
r, Plotly, and Shiny. Chapman; Hall/CRC.
https://plotly-r.com.
Verbosio, Fabio, Arne De Coninck, Drosos Kourounis, and Olaf Schenk.
2017.
“Enhancing the Scalability of Selected Inversion
Factorization Algorithms in Genomic Prediction.” Journal of
Computational Science 22 (Supplement C): 99–108.
https://doi.org/10.1016/j.jocs.2017.08.013.
Xie, Yihui. 2014. “knitr: A
Comprehensive Tool for Reproducible Research in R.”
In Implementing Reproducible Computational Research, edited by
Victoria Stodden, Friedrich Leisch, and Roger D. Peng. Chapman;
Hall/CRC.
———. 2015.
Dynamic Documents with R and Knitr. 2nd
ed. Boca Raton, Florida: Chapman; Hall/CRC.
https://yihui.org/knitr/.
———. 2024.
knitr: A General-Purpose
Package for Dynamic Report Generation in r.
https://yihui.org/knitr/.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2018.
R Markdown:
The Definitive Guide. Boca Raton, Florida: Chapman; Hall/CRC.
https://bookdown.org/yihui/rmarkdown.
Xie, Yihui, Christophe Dervieux, and Emily Riederer. 2020.
R
Markdown Cookbook. Boca Raton, Florida: Chapman; Hall/CRC.
https://bookdown.org/yihui/rmarkdown-cookbook.
Yuan, Yuan, Bachl, Fabian E., Lindgren, Finn, Borchers, et al. 2017.
“Point Process Models for Spatio-Temporal Distance Sampling Data
from a Large-Scale Survey of Blue Whales.” Ann. Appl.
Stat. 11 (4): 2270–97.
https://doi.org/10.1214/17-AOAS1078.
LS0tCnRpdGxlOiAiU29sdmluZyBhIHBhcmFib2xpYyBlcXVhdGlvbiIKZGF0ZTogIkNyZWF0ZWQ6IDIwLTA0LTIwMjUuIExhc3QgbW9kaWZpZWQ6IGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQtJW0tJVkuJylgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIG1hdGhqYXg6ICJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL21hdGhqYXhAMy9lczUvdGV4LW1tbC1jaHRtbC5qcyIKICAgIGhpZ2hsaWdodDogcHlnbWVudHMKICAgIHRoZW1lOiBmbGF0bHkKICAgIGNvZGVfZm9sZGluZzogc2hvdyAjIGNsYXNzLnNvdXJjZSA9ICJmb2xkLWhpZGUiIHRvIGhpZGUgY29kZSBhbmQgYWRkIGEgYnV0dG9uIHRvIHNob3cgaXQKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogdHJ1ZQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQphbHdheXNfYWxsb3dfaHRtbDogdHJ1ZQpiaWJsaW9ncmFwaHk6IAogIC0gcmVmZXJlbmNlcy5iaWIKICAtIGdyYXRlZnVsLXJlZnMuYmliCmhlYWRlci1pbmNsdWRlczoKICAtIFxuZXdjb21tYW5ke1xhcn17XG1hdGhiYntSfX0KICAtIFxuZXdjb21tYW5ke1xsbGF2fVsxXXtcbGVmdFx7IzFccmlnaHRcfX0KICAtIFxuZXdjb21tYW5ke1xwYXJlfVsxXXtcbGVmdCgjMVxyaWdodCl9CiAgLSBcbmV3Y29tbWFuZHtcTmNhbH17XG1hdGhjYWx7Tn19CiAgLSBcbmV3Y29tbWFuZHtcVmNhbH17XG1hdGhjYWx7Vn19CiAgLSBcbmV3Y29tbWFuZHtcRWNhbH17XG1hdGhjYWx7RX19CiAgLSBcbmV3Y29tbWFuZHtcV2NhbH17XG1hdGhjYWx7V319Ci0tLQoKYGBge3IgeGFyaW5nYW5FeHRyYS1jbGlwYm9hcmQsIGVjaG8gPSBGQUxTRX0KaHRtbHRvb2xzOjp0YWdMaXN0KAogIHhhcmluZ2FuRXh0cmE6OnVzZV9jbGlwYm9hcmQoCiAgICBidXR0b25fdGV4dCA9ICI8aSBjbGFzcz1cImZhLXNvbGlkIGZhLWNsaXBib2FyZFwiIHN0eWxlPVwiY29sb3I6ICMwMDAwOEJcIj48L2k+IiwKICAgIHN1Y2Nlc3NfdGV4dCA9ICI8aSBjbGFzcz1cImZhIGZhLWNoZWNrXCIgc3R5bGU9XCJjb2xvcjogIzkwQkU2RFwiPjwvaT4iLAogICAgZXJyb3JfdGV4dCA9ICI8aSBjbGFzcz1cImZhIGZhLXRpbWVzLWNpcmNsZVwiIHN0eWxlPVwiY29sb3I6ICNGOTQxNDRcIj48L2k+IgogICksCiAgcm1hcmtkb3duOjpodG1sX2RlcGVuZGVuY3lfZm9udF9hd2Vzb21lKCkKKQpgYGAKCgpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9CmJvZHkgLm1haW4tY29udGFpbmVyIHsKICBtYXgtd2lkdGg6IDEwMCUgIWltcG9ydGFudDsKICB3aWR0aDogMTAwJSAhaW1wb3J0YW50Owp9CmJvZHkgewogIG1heC13aWR0aDogMTAwJSAhaW1wb3J0YW50Owp9Cgpib2R5LCB0ZCB7CiAgIGZvbnQtc2l6ZTogMTZweDsKfQpjb2RlLnJ7CiAgZm9udC1zaXplOiAxNHB4Owp9CnByZSB7CiAgZm9udC1zaXplOiAxNHB4Cn0KLmN1c3RvbS1ib3ggewogIGJhY2tncm91bmQtY29sb3I6ICNmNWY3ZmE7IC8qIExpZ2h0IGdyZXktYmx1ZSBiYWNrZ3JvdW5kICovCiAgYm9yZGVyLWNvbG9yOiAjZTFlOGVkOyAvKiBMaWdodCBib3JkZXIgY29sb3IgKi8KICBjb2xvcjogIzJjM2U1MDsgLyogRGFyayB0ZXh0IGNvbG9yICovCiAgcGFkZGluZzogMTVweDsgLyogUGFkZGluZyBpbnNpZGUgdGhlIGJveCAqLwogIGJvcmRlci1yYWRpdXM6IDVweDsgLyogUm91bmRlZCBjb3JuZXJzICovCiAgbWFyZ2luLWJvdHRvbTogMjBweDsgLyogU3BhY2luZyBiZWxvdyB0aGUgYm94ICovCn0KLmNhcHRpb24gewogIG1hcmdpbjogYXV0bzsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgbWFyZ2luLWJvdHRvbTogMjBweDsgLyogU3BhY2luZyBiZWxvdyB0aGUgYm94ICovCn0KYGBgCgoKTGV0IHVzIHNldCBzb21lIGdsb2JhbCBvcHRpb25zIGZvciBhbGwgY29kZSBjaHVua3MgaW4gdGhpcyBkb2N1bWVudC4KCgpgYGB7cn0KIyBTZXQgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5CnNldC5zZWVkKDE5ODIpIAojIFNldCBnbG9iYWwgb3B0aW9ucyBmb3IgYWxsIGNvZGUgY2h1bmtzCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAjIERpc2FibGUgbWVzc2FnZXMgcHJpbnRlZCBieSBSIGNvZGUgY2h1bmtzCiAgbWVzc2FnZSA9IEZBTFNFLCAgICAKICAjIERpc2FibGUgd2FybmluZ3MgcHJpbnRlZCBieSBSIGNvZGUgY2h1bmtzCiAgd2FybmluZyA9IEZBTFNFLCAgICAKICAjIFNob3cgUiBjb2RlIHdpdGhpbiBjb2RlIGNodW5rcyBpbiBvdXRwdXQKICBlY2hvID0gVFJVRSwgICAgICAgIAogICMgSW5jbHVkZSBib3RoIFIgY29kZSBhbmQgaXRzIHJlc3VsdHMgaW4gb3V0cHV0CiAgaW5jbHVkZSA9IFRSVUUsICAgICAKICAjIEV2YWx1YXRlIFIgY29kZSBjaHVua3MKICBldmFsID0gVFJVRSwgICAgICAgCiAgIyBFbmFibGUgY2FjaGluZyBvZiBSIGNvZGUgY2h1bmtzIGZvciBmYXN0ZXIgcmVuZGVyaW5nCiAgY2FjaGUgPSBGQUxTRSwgICAgICAKICAjIEFsaWduIGZpZ3VyZXMgaW4gdGhlIGNlbnRlciBvZiB0aGUgb3V0cHV0CiAgZmlnLmFsaWduID0gImNlbnRlciIsCiAgIyBFbmFibGUgcmV0aW5hIGRpc3BsYXkgZm9yIGhpZ2gtcmVzb2x1dGlvbiBmaWd1cmVzCiAgcmV0aW5hID0gMiwKICAjIFNob3cgZXJyb3JzIGluIHRoZSBvdXRwdXQgaW5zdGVhZCBvZiBzdG9wcGluZyByZW5kZXJpbmcKICBlcnJvciA9IFRSVUUsCiAgIyBEbyBub3QgY29sbGFwc2UgY29kZSBhbmQgb3V0cHV0IGludG8gYSBzaW5nbGUgYmxvY2sKICBjb2xsYXBzZSA9IEZBTFNFCikKYGBgCgoKCgpgYGB7cn0KIyBpbmxhLnVwZ3JhZGUodGVzdGluZyA9IFRSVUUpCiMgcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoImlubGFicnUtb3JnL2lubGFicnUiLCByZWYgPSAiZGV2ZWwiKQojIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJkYXZpZGJvbGluL3JzcGRlIiwgcmVmID0gImRldmVsIikKIyByZW1vdGVzOjppbnN0YWxsX2dpdGh1YigiZGF2aWRib2xpbi9tZXRyaWNncmFwaCIsIHJlZiA9ICJkZXZlbCIpCmxpYnJhcnkoSU5MQSkKbGlicmFyeShpbmxhYnJ1KQpsaWJyYXJ5KHJTUERFKQpsaWJyYXJ5KE1ldHJpY0dyYXBoKQpsaWJyYXJ5KGdyYXRlZnVsKQoKbGlicmFyeShwbG90bHkpCmBgYAoKCldlIHdhbnQgdG8gc29sdmUgdGhlIGZyYWN0aW9uYWwgZGlmZnVzaW9uIGVxdWF0aW9uClxiZWdpbntlcXVhdGlvbn0KXGxhYmVse2VxOm1haW5lcX0KICAgIFxwYXJ0aWFsX3QgdSsoXGthcHBhXjItXERlbHRhX1xHYW1tYSlee1xmcmFje1xhbHBoYX17Mn19IHU9ZiBcdGV4dCB7IG9uIH0gXEdhbW1hIFx0aW1lcygwLCBUKSwgXHF1YWQgdSgwKT11XzAgXHRleHQgeyBvbiB9IFxHYW1tYSwKXGVuZHtlcXVhdGlvbn0Kd2hlcmUgJHUkIHNhdGlzZmllcyB0aGUgS2lyY2hob2ZmIHZlcnRleCBjb25kaXRpb25zClxiZWdpbntlcXVhdGlvbn0KXGxhYmVse2VxOktjb25kfQogICAgXGxlZnRce1xwaGlcaW4gQyhcR2FtbWEpXDtcQmlnfFw7IFxmb3JhbGwgdlxpbiBWOiBcc3VtX3tlXGluXG1hdGhjYWx7RX1fdn1ccGFydGlhbF9lIFxwaGkodik9MCBccmlnaHRcfQpcZW5ke2VxdWF0aW9ufQoKTGV0IHVzIHN0YXJ0IGJ5IGJ1aWxkaW5nIGEgZ3JhcGguCgpgYGB7cn0KZ3JhcGggPC0gbWV0cmljX2dyYXBoJG5ldyhwZXJmb3JtX21lcmdlcyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRvbGVyYW5jZSA9IGxpc3QoZWRnZV9lZGdlID0gMWUtMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJ0ZXhfdmVydGV4ID0gMWUtMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlX3ZlcnRleCA9IDFlLTMpKQpncmFwaCRwbG90KCkKZ3JhcGgkYnVpbGRfbWVzaChoID0gMC4wNSkKYGBgCgpMZXQgJFxhbHBoYVxpbigwLDJdJCBhbmQgJFVfaF5cdGF1JCBkZW5vdGUgdGhlIHNlcXVlbmNlIG9mIGFwcHJveGltYXRpb25zIG9mIHRoZSBzb2x1dGlvbiB0byB0aGUgd2VhayBmb3JtIG9mIHByb2JsZW0gXGVxcmVme2VxOm1haW5lcX0gYXQgZWFjaCB0aW1lIHN0ZXAgb24gYSBtZXNoIGluZGV4ZWQgYnkgJGgkLiBMZXQgJHo9MCQgYW5kICRVXjBfaCA9IFBfaHVfMCQuIEZvciAkaz0wLFxkb3RzLCBOLTEkLCAkVV9oXntrKzF9XGluIFZfaCQgc29sdmVzIHRoZSBmb2xsb3dpbmcgc2NoZW1lClxiZWdpbnthbGlnbn0KXGxhYmVse3N5c3RlbTpmdWxseV9kaXNjcmV0ZV9zY2hlbWV9CiAgICAgICAgXGxhbmdsZVxkZWx0YSBVX2hee2srMX0sXHBoaVxyYW5nbGUgKyBcbWF0aGZyYWt7YX0oVV9oXntrKzF9LFxwaGkpID0gXGxhbmdsZSBmXntrKzF9LFxwaGlccmFuZ2xlICxccXVhZFxmb3JhbGxccGhpXGluIFZfaCwKXGVuZHthbGlnbn0Kd2hlcmUgJGZee2srMX0gPSBcZGlzcGxheXN0eWxlXGRmcmFjezF9e1x0YXV9XGludF97dF9rfV57dF57aysxfX1mKHQpZHQkLgpUaGUgc29sdXRpb24gY2FuIGJlIHJlcHJlc2VudGVkIGFzIApcYmVnaW57YWxpZ24qfQogICAgVV9oXmsocykgPSAgXHN1bV97aj0xfV57Tl9ofXVfal5rXHBzaV9qKHMpClxlbmR7YWxpZ24qfQpSZXBsYWNpbmcgdGhpcyBpbnRvIFxlcXJlZntzeXN0ZW06ZnVsbHlfZGlzY3JldGVfc2NoZW1lfSB5aWVsZHMgdGhlIGZvbGxvd2luZyBsaW5lYXIgc3lzdGVtClxiZWdpbnthbGlnbip9CiAgICBcc3VtX3tqPTF9XntOX2h9dV9qXntrKzF9WyhccHNpX2osXHBzaV9pKV97TF8yKFxHYW1tYSl9KyBcdGF1XG1hdGhmcmFre2F9KFxwc2lfaixccHNpX2kpXSA9IFxzdW1fe2o9MX1ee05faH11X2pee2t9KFxwc2lfaixccHNpX2kpX3tMXzIoXEdhbW1hKX0rXHRhdSggZl57aysxfSxccHNpX2kpX3tMXzIoXEdhbW1hKX0KXGVuZHthbGlnbip9CmZvciAkaSA9IDEsXGRvdHMsIE5faCQuIEluIG1hdHJpeCBub3RhdGlvbiwKXGJlZ2lue2FsaWdufQpcbGFiZWx7ZGlmZl9lcV9kaXNjcmV0ZX0KICAgIChDK1x0YXUgQSlVXntrKzF9ID0gQ1VeaytcdGF1IEZee2srMX0sClxlbmR7YWxpZ259CndoZXJlICRDJCBoYXMgZW50cmllcyAkQ197aWp9ID0gKFxwc2lfaixccHNpX2kpX3tMXzIoXEdhbW1hKX0kLCAkQSQgaGFzIGVudHJpZXMgJEFfe2lqfSA9IFxtYXRoZnJha3thfShccHNpX2osXHBzaV9pKSQsICRVXmskIGhhcyBlbnRyaWVzICR1X2peayQsIGFuZCAkRl5rJCBoYXMgZW50cmllcyAkKCBmXntrfSxccHNpX2kpX3tMXzIoXEdhbW1hKX0kLiBCeSBtdWx0aXBseWluZyBib3RoIHNpZGVzIGJ5ICRBXnstMX0kIGFuZCBjb25zaWRlcmluZyBpdHMgb3BlcmF0b3ItYmFzZWQgcmF0aW9uYWwgYXBwcm94aW1hdGlvbiAkUF9cZWxsXnstMX1QX3IkLCB3ZSBhcnJpdmUgYXQgJChQX3JDK1x0YXUgUF9cZWxsKVVee2srMX0gPSBQX3IoQ1VeaytcdGF1IEZee2srMX0pJC4KCmBgYHtyfQojIENvbXB1dGUgdGhlIEZFTSBtYXRyaWNlcwpncmFwaCRjb21wdXRlX2ZlbSgpCkcgPC0gZ3JhcGgkbWVzaCRHCkMgPC0gZ3JhcGgkbWVzaCRDCnggPC0gZ3JhcGgkbWVzaCRWWywgMV0KeSA8LSBncmFwaCRtZXNoJFZbLCAyXQojIEluaXRpYWwgY29uZGl0aW9uClVfMCA8LSAxMCpleHAoLSgoeC00KV4yICsgKHktNCleMikpCiMgRGVmaW5lIHRoZSB0aW1lIHN0ZXAKdGltZV9zdGVwIDwtIDAuMQojIERlZmluZSB0aGUgcmlnaHQtaGFuZCBzaWRlIGZ1bmN0aW9uCmZ1biA8LSBmdW5jdGlvbih0KSB7cmV0dXJuKHNpbih0KSooKHgtNCleMiAtICh5LTQpXjIpKX0KIyBEZWZpbmUgdGhlIHRpbWUgZGlzY3JldGl6YXRpb24KdGltZV9zZXEgPC0gc2VxKDAscGksIGJ5ID0gdGltZV9zdGVwKQojIENvbXB1dGUgdGhlIHJpZ2h0LWhhbmQgc2lkZSBmdW5jdGlvbiBhdCBlYWNoIHRpbWUgc3RlcApmdW5fbWF0IDwtIGRvLmNhbGwoY2JpbmQsIGxhcHBseSh0aW1lX3NlcSwgZnVuKSkKIyBEZWZpbmUgdGhlIHBhcmFtZXRlcnMKa2FwcGEgPC0gMQpMIDwtIGthcHBhXjIqQyArIEcKYWxwaGEgPC0gMC44CmJldGEgPC0gYWxwaGEvMgpvcCA8LSBmcmFjdGlvbmFsLm9wZXJhdG9ycyhMLCBiZXRhLCBDLCBzY2FsZS5mYWN0b3IgPSBrYXBwYV4yLCBtID0gMSkKUGwgPC0gb3AkUGwKUHIgPC0gb3AkUHIKZnVuRiA8LSBDICUqJSBmdW5fbWF0IApgYGAKCgpgYGB7cn0KIyBQcmVjb21wdXRlIHRoZSBMSFMgbWF0cml4CkxIUyA8LSBQciAlKiUgQyArIHRpbWVfc3RlcCAqIFBsCiMgSW5pdGlhbGl6ZSBVIG1hdHJpeCB0byBzdG9yZSBzb2x1dGlvbiBhdCBlYWNoIHRpbWUgc3RlcApVX21hdCA8LSBtYXRyaXgoTkEsIG5yb3cgPSBucm93KEMpLCBuY29sID0gbGVuZ3RoKHRpbWVfc2VxKSkKVV9tYXRbLCAxXSA8LSBVXzAKCiMgVGltZS1zdGVwcGluZyBsb29wCmZvciAoayBpbiAxOihsZW5ndGgodGltZV9zZXEpIC0gMSkpIHsKICBSSFMgPC0gUHIgJSolIChDICUqJSBVX21hdFssIGtdICsgdGltZV9zdGVwICogZnVuRlssIGsgKyAxXSkKICBVX21hdFssIGsgKyAxXSA8LSBhcy5tYXRyaXgoc29sdmUoTEhTLCBSSFMpKQp9CmBgYAoKCmBgYHtyfQojIFBsb3QgdGhlIGluaXRpYWwgY29uZGl0aW9uCnBfaW5pIDwtIGdyYXBoJHBsb3RfZnVuY3Rpb24oWCA9IFVfMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVydGV4X3NpemUgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gInBsb3RseSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkZ2VfY29sb3IgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlX3dpZHRoID0gMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9jb2xvciA9ICJibHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV93aWR0aCA9IDMpCnBfaW5pCiMgUGxvdCB0aGUgbW92aWUgb2YgZgpwX2YgPC0gZ3JhcGgkcGxvdF9tb3ZpZShmdW5fbWF0KQpwX2YkeCRsYXlvdXQkc2NlbmUkeGF4aXMkcmFuZ2UgPC0gcmFuZ2UoeCkKcF9mJHgkbGF5b3V0JHNjZW5lJHlheGlzJHJhbmdlIDwtIHJhbmdlKHkpCnBfZiR4JGxheW91dCRzY2VuZSR6YXhpcyRyYW5nZSA8LSByYW5nZShmdW5fbWF0KQpwX2YKIyBQbG90IHRoZSBtb3ZpZSBvZiB0aGUgc29sdXRpb24KcF9zb2wgPC0gZ3JhcGgkcGxvdF9tb3ZpZShVX21hdCkKcF9zb2wkeCRsYXlvdXQkc2NlbmUkeGF4aXMkcmFuZ2UgPC0gcmFuZ2UoeCkKcF9zb2wkeCRsYXlvdXQkc2NlbmUkeWF4aXMkcmFuZ2UgPC0gcmFuZ2UoeSkKcF9zb2wkeCRsYXlvdXQkc2NlbmUkemF4aXMkcmFuZ2UgPC0gcmFuZ2UoVV9tYXQpCnBfc29sCmBgYAoKCgojIFJlZmVyZW5jZXMKCmBgYHtyfQpjaXRlX3BhY2thZ2VzKG91dHB1dCA9ICJwYXJhZ3JhcGgiLCBvdXQuZGlyID0gIi4iKQpgYGAK